## Rescale the other distance matrices
rescale01 <- function(x) {
  (x - min(x, na.rm = TRUE)) / (max(x, na.rm = TRUE) - min(x, na.rm = TRUE))
}

scalar.dist <- function(var, scalefactor = 1, int = TRUE) {
  ## Utility function to make n x n abs dist matrices
  outer(var, var, FUN = function(x, y) {
    if (int) {
      as.integer(abs(x - y) * scalefactor)
    } else {
      abs(x - y) * scalefactor
    }
  })
}


## Define awesome function
nbmplot <- function(thedata, xvar, yvar, strata, main = NULL, ylim = c(0, 1), points = FALSE, ylab = NULL, xlab = NULL,
                    xlim = NULL, ...) {
  thedata <- as.data.frame(thedata) ## just to avoid problems generated from tibbles
  ## Scatterplot with pairs connected by segments
  thedata <- na.omit(thedata[, c(xvar, yvar, strata)])
  if (is.null(main)) {
    main <- strata
  }
  if (is.null(xlab)) {
    xlab <- xvar
  }
  if (is.null(ylab)) {
    ylab <- yvar
  }
  if (is.null(xlim)) {
    xlim <- range(thedata[, xvar], na.rm = TRUE)
  }

  if (points) {
    plot(thedata[[xvar]], thedata[[yvar]],
      pch = as.numeric(thedata[, strata]),
      ylim = ylim, xlim = xlim,
      xlab = xlab, ylab = ylab, main = main
    )
  } else {
    plot(thedata[[xvar]], thedata[[yvar]],
      type = "n",
      ylim = ylim, xlim = xlim,
      xlab = xlab, ylab = ylab, main = main
    )
  }

  gooddata <- thedata[thedata[, strata] %in% names(table(thedata[, strata])[table(thedata[, strata]) == 2]), , drop = TRUE]
  gooddata[, strata] <- factor(gooddata[, strata]) ## trick to drop unused levels

  thesets <- sapply(split(gooddata[, c(xvar, yvar)], gooddata[, strata]), function(dat) {
    unlist(dat)
  })
  segments(thesets[1, ], thesets[3, ], thesets[2, ], thesets[4, ], ...)
}



rank.pairs <- function(x, block) { ## Identify the low and high subj in each pair
  unsplit(lapply(split(x, block), function(x) {
    rank(x)
  }), block)
}



align.by.block <- function(x, block, fn = mean, thenames = NULL) { ## By default, this rescales each observation to be the distance from the group mean.
  newx <- unsplit(lapply(split(x, block), function(x) {
    x - fn(x)
  }), block)
  if (!is.null(names)) {
    names(newx) <- thenames
  }
  return(newx)
}


#' Function to convert the output of nmatch into a factor variable for use in analysis
#' Depends on use of nmatch in designmatch
nmatch_to_df <- function(obj, origid) {
  ## We want a factor that we can merge onto our
  ## existing dataset. Here returning a data.frame so that
  ## we can merge --- seems less error prone than using
  ## rownames even if it is slower.
  matchesdat <- data.frame(
    pair = obj$group_id,
    match_id = c(obj$id_1, obj$id_2)
  )
  matchesdat$id <- origid[matchesdat$match_id]
  return(matchesdat)
}
